package com.litong.spring.mvc.redis.component;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;

import com.fasterxml.jackson.core.JsonParseException;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JavaType;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.type.TypeFactory;

@Component
public class SpringRedisUtil {
  @Autowired
  private StringRedisTemplate stringRedisTemplate;

  public static final ObjectMapper mapper = new ObjectMapper();

  public void saveString(String key, String value) {
    stringRedisTemplate.opsForValue().set(key, value);
  }

  public String getString(String key) {
    String retval = stringRedisTemplate.opsForValue().get(key);
    return retval;
  }

  public void saveBean(String key, Object object) {
    String value = null;
    try {
      value = mapper.writeValueAsString(object);
    } catch (JsonProcessingException e) {
      e.printStackTrace();
      return;
    }
    saveString(key, value);
  }

  public <T> T getBean(String key, Class<T> clazz) {
    String string = getString(key);
    if (string == null) {
      return null;
    }
    return readValue(clazz, string);
  }

  private <T> T readValue(Class<T> clazz, String string) {
    try {
      return mapper.readValue(string, clazz);
    } catch (JsonParseException e) {
      e.printStackTrace();
    } catch (JsonMappingException e) {
      e.printStackTrace();
    } catch (IOException e) {
      e.printStackTrace();
    }
    return null;
  }

  public void delete(String key) {
    stringRedisTemplate.delete(key);
  }

  public void delete(Collection<String> keys) {
    stringRedisTemplate.delete(keys);
  }

  private <T> T readValue(JavaType javaType, String string) {
    try {
      return mapper.readValue(string, javaType);
    } catch (JsonParseException e) {
      e.printStackTrace();
    } catch (JsonMappingException e) {
      e.printStackTrace();
    } catch (IOException e) {
      e.printStackTrace();
    }
    return null;
  }

  public <T> T getBean(String key, JavaType javaType) {
    String string = getString(key);
    return readValue(javaType, string);
  }

  public <T> T getListBean(String key, Class<?>... parameterClasses) {
    TypeFactory typeFactory = mapper.getTypeFactory();
    JavaType javaType = typeFactory.constructParametrizedType(ArrayList.class, ArrayList.class, parameterClasses);
    return getBean(key, javaType);
  }
}